home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Cream of the Crop 1
/
Cream of the Crop 1.iso
/
PROGRAM
/
UUPC11QS.ARJ
/
DCP.C
< prev
next >
Wrap
C/C++ Source or Header
|
1991-11-23
|
17KB
|
525 lines
/*
For best results in visual layout while viewing this file, set
tab stops to every 4 columns.
*/
/*
dcp.c
Revised edition of dcp
Stuart Lynne May/87
Copyright (c) Richard H. Lamb 1985, 1986, 1987
Changes Copyright (c) Stuart Lynne 1987
Changes Copyright (c) Andrew H. (Drew) Derbyshire 1989, 1990
Maintenance Notes:
25Aug87 - Added a version number - Jal
25Aug87 - Return 0 if contact made with host, or 5 otherwise.
04Sep87 - Bug causing premature sysend() fixed. - Randall Jessup.
13May89 - Add date to version message - Drew Derbyshire
17May89 - Add '-u' (until) option for login processing
01 Oct 89 Add missing function prototypes ahd
28 Nov 89 Add parse of incoming user id for From record ahd
18 Mar 90 Change checktime() calls to Microsoft C 5.1 ahd
*/
/* "DCP" a uucp clone. Copyright Richard H. Lamb 1985,1986,1987 */
/*
This program implements a uucico type file transfer and remote
execution protocol.
Usage: uuio [-s sys] [-r 0|1] [-x debug]
e.g.
uuio [-x n] -r 0 [-u time] client mode, wait for an incoming call
until 'time'.
uuio [-x n] -s HOST call the host "HOST".
uuio [-x n] -s all call all known hosts in the systems file.
uuio [-x n] -s any call any host we have work queued for.
uuio [-x n] same as the above.
*/
#include <stdio.h> /* ahd */
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
/*--------------------------------------------------------------------*/
/* UUPC/extended prototypes */
/*--------------------------------------------------------------------*/
#include "lib.h"
#include "arpadate.h"
#include "checktim.h"
#include "dcp.h"
#include "dcplib.h"
#include "dcpstats.h"
#include "dcpsys.h"
#include "dcpxfer.h"
#include "getopt.h"
#include "hlib.h"
#include "hostable.h"
#include "hostatus.h"
#include "modem.h"
#include "security.h"
#include "ssleep.h"
/*--------------------------------------------------------------------*/
/* Define passive and active polling modes; passive is */
/* sometimes refered to as "slave", "active" as master. Since */
/* the roles can actually switch during processing, we avoid */
/* the terms here */
/*--------------------------------------------------------------------*/
typedef enum {
POLL_PASSIVE = 0, /* We answer the telephone */
POLL_ACTIVE = 1 /* We call out to another host */
} POLL_MODE ;
/*--------------------------------------------------------------------*/
/* Global variables */
/*--------------------------------------------------------------------*/
size_t pktsize; /* packet size for this protocol*/
FILE *xfer_stream = NULL; /* stream for file being handled */
boolean callnow = FALSE; /* TRUE = ignore time in L.SYS */
FILE *fwork = NULL, *fsys= NULL ;
FILE *syslog = NULL;
char workfile[FILENAME_MAX]; /* name of current workfile */
char *Rmtname = nil(char); /* system we want to call */
char rmtname[20]; /* system we end up talking to */
char s_systems[FILENAME_MAX]; /* full-name of systems file */
struct HostTable *hostp;
struct HostStats remote_stats; /* host status, as defined by hostatus */
static boolean dialed = FALSE;/* True = We attempted a phone call */
currentfile();
/*--------------------------------------------------------------------*/
/* Local function prototypes */
/*--------------------------------------------------------------------*/
static CONN_STATE process( const POLL_MODE poll_mode );
static void cant(char *file);
/*--------------------------------------------------------------------*/
/* d c p m a i n */
/* */
/* main program for DCP, called by uuhost */
/*--------------------------------------------------------------------*/
int dcpmain(int argc, char *argv[])
{
boolean Contacted = FALSE;
int option;
int poll_mode = POLL_ACTIVE; /* Default = dial out to system */
char *logintime = nil(char); /* Length of time to wait for login */
char *hotuser = NULL;
BPS hotbaud = 0;
fwork = nil(FILE);
/*--------------------------------------------------------------------*/
/* Process our options */
/*--------------------------------------------------------------------*/
while ((option = getopt(argc, argv, "r:s:u:w:x:z:n?")) != EOF)
switch (option) {
case 'n':
callnow = TRUE;
break;
case 'r':
poll_mode = atoi(optarg);
break;
case 's':
Rmtname = strdup(optarg);
break;
case 'u':
logintime = strdup(optarg);
break;
case 'x':
debuglevel = atoi(optarg);
break;
case 'z':
hotbaud = atoi(optarg);
break;
case 'w':
poll_mode = 0; /* Presume passive polling */
hotuser = optarg;
break;
case '?':
puts("\nUsage:\tuucico [-s sys] [-r 1|0]\
[-x debug] [-u time] [-n] [-w user] [-z bps]");
return 4;
}
/*--------------------------------------------------------------------*/
/* Abort if any options were left over */
/*--------------------------------------------------------------------*/
if (optind != argc) {
puts("Extra parameter(s) at end.");
return 4;
}
if (Rmtname == nil(char))
Rmtname = "any";
/*--------------------------------------------------------------------*/
/* Initialize logging and the name of the systems file */
/*--------------------------------------------------------------------*/
if ((logfile = FOPEN(LOGFILE, "a", TEXT)) == nil(FILE))
cant(LOGFILE);
if (bflag[F_SYSLOG])
{
if ((syslog = FOPEN(SYSLOG, "a", TEXT)) == nil(FILE))
cant(SYSLOG);
} /* if (bflag[F_SYSLOG]) */
/*--------------------------------------------------------------------*/
/* logecho = ((poll_mode == POLL_ACTIVE) ? TRUE : FALSE); */
/*--------------------------------------------------------------------*/
logecho = TRUE; /* ahd - One too many missed messages */
mkfilename(s_systems, confdir, SYSTEMS);
printmsg(2, "Using system file '%s'",s_systems);
/*--------------------------------------------------------------------*/
/* Load connection stats for previous runs */
/*--------------------------------------------------------------------*/
HostStatus();
/*--------------------------------------------------------------------*/
/* Initialize security */
/*--------------------------------------------------------------------*/
if ( !LoadSecurity())
{
printmsg(0,"Unable to initialize security, see previous message");
panic();
}
/*--------------------------------------------------------------------*/
/* Begin main processing loop */
/*--------------------------------------------------------------------*/
if (poll_mode == POLL_ACTIVE) {
CONN_STATE m_state = CONN_INITIALIZE;
printmsg(2, "calling \"%s\", debug=%d", Rmtname, debuglevel);
if ((fsys = FOPEN(s_systems, "r", TEXT)) == nil(FILE))
exit(FAILED);
while (m_state != CONN_EXIT )
{
printmsg(4, "M state = %c", m_state);
switch (m_state)
{
case CONN_INITIALIZE:
m_state = getsystem();
break;
case CONN_CALLUP:
dialed = TRUE;
m_state = callup();
break;
case CONN_PROTOCOL:
m_state = startup_server();
break;
case CONN_SERVER:
m_state = process( poll_mode );
Contacted = TRUE;
break;
case CONN_TERMINATE:
m_state = sysend();
break;
case CONN_DROPLINE:
shutdown();
m_state = CONN_INITIALIZE;
case CONN_EXIT:
break;
default:
printmsg(0,"dcpmain: Unknown master state = %c",m_state );
panic();
break;
} /* switch */
} /* while */
fclose(fsys);
}
else { /* client mode */
CONN_STATE s_state = CONN_INITIALIZE;
if (logintime != NULL)
{
if (!checktime(logintime,(time_t) 0))
printmsg(1,"dcpmain: awaiting login window %s",logintime);
while(!checktime(logintime,(time_t) 0) ) /* Wait for window */
ssleep(60); /* Checking one per minute */
printmsg(2,"Enabling %s for remote login until '%s'",
E_inmodem, logintime);
}
while (s_state != CONN_EXIT )
{
printmsg(4, "S state = %c", s_state);
switch (s_state) {
case CONN_INITIALIZE:
if ( hotuser == NULL )
s_state = CONN_ANSWER;
else
s_state = CONN_HOTMODEM;
break;
case CONN_ANSWER:
s_state = callin( logintime );
break;
case CONN_HOTMODEM:
s_state = callhot( hotbaud );
break;
case CONN_HOTLOGIN:
s_state = loginbypass( hotuser );
break;
case CONN_LOGIN:
s_state = login();
break;
case CONN_PROTOCOL:
s_state = startup_client();
break;
case CONN_CLIENT:
Contacted = TRUE;
s_state = process( poll_mode );
break;
case CONN_TERMINATE:
s_state = sysend();
break;
case CONN_DROPLINE:
shutdown();
s_state = CONN_EXIT;
case CONN_EXIT:
break;
default:
printmsg(0,"dcpmain: Unknown slave state = %c",s_state );
panic();
break;
} /* switch */
} /* while */
} /* else */
/*--------------------------------------------------------------------*/
/* Report our results */
/*--------------------------------------------------------------------*/
if (!Contacted)
{
if (dialed)
printmsg(0, "Could not connect to remote system.");
else
printmsg(0, "No work for requested system or wrong time to call.");
}
dcupdate();
fclose(logfile);
logfile = stdout;
if (bflag[F_SYSLOG])
fclose(syslog);
return Contacted ? 0 : 5;
} /*dcpmain*/
/*--------------------------------------------------------------------*/
/* p r o c e s s */
/* */
/* The procotol state machine */
/*--------------------------------------------------------------------*/
static CONN_STATE process( const POLL_MODE poll_mode )
{
boolean master;
XFER_STATE state = ( poll_mode == POLL_ACTIVE ) ? XFER_SENDINIT :
XFER_RECVINIT;
XFER_STATE old_state = XFER_EXIT;
/* Initialized to any state but the
original value of "state" */
XFER_STATE save_state = XFER_EXIT;
/*--------------------------------------------------------------------*/
/* Yea old state machine for the high level file transfer procotol */
/*--------------------------------------------------------------------*/
while( state != XFER_EXIT )
{
printmsg(state == old_state ? 14 : 4 ,
"process: Machine state is = %c", state );
old_state = state;
switch( state )
{
case XFER_SENDINIT: /* Initialize outgoing protocol */
state = sinit();
break;
case XFER_RECVINIT: /* Initialize Receive protocol */
state = rinit();
break;
case XFER_MASTER: /* Begin master mode */
master = TRUE;
state = XFER_NEXTJOB;
break;
case XFER_SLAVE: /* Begin slave mode */
master = FALSE;
state = XFER_RECVHDR;
break;
case XFER_NEXTJOB: /* Look for work in local queue */
state = scandir( rmtname );
break;
case XFER_REQUEST: /* Process next file in current job
in queue */
state = newrequest();
break;
case XFER_PUTFILE: /* Got local tranmit request */
state = ssfile();
break;
case XFER_GETFILE: /* Got local tranmit request */
state = srfile();
break;
case XFER_SENDDATA: /* Remote accepted our work, send data */
state = sdata();
break;
case XFER_SENDEOF: /* File xfer complete, send EOF */
state = seof( master );
break;
case XFER_FILEDONE: /* Receive or transmit is complete */
state = master ? XFER_REQUEST : XFER_RECVHDR;
break;
case XFER_NOLOCAL: /* No local work, remote have any? */
state = sbreak();
break;
case XFER_NOREMOTE: /* No remote work, local have any? */
state = schkdir( poll_mode == POLL_ACTIVE );
break;
case XFER_RECVHDR: /* Receive header from other host */
state = rheader();
break;
case XFER_TAKEFILE: /* Set up to receive remote requested
file transfer */
state = rrfile();
break;
case XFER_GIVEFILE: /* Set up to transmit remote
requuest file transfer */
state = rsfile();
break;
case XFER_RECVDATA: /* Receive file data from other host */
state = rdata();
break;
case XFER_RECVEOF:
state = reof();
break;
case XFER_LOST: /* Lost the other host, flame out */
printmsg(0,"process: Connection lost to %s, \
previous system state = %c", rmtname, save_state );
state = XFER_EXIT;
break;
case XFER_ABORT: /* Internal error, flame out */
printmsg(0,"process: Aborting connection to %s, \
previous system state = %c", rmtname, save_state );
state = XFER_ENDP;
break;
case XFER_ENDP: /* Terminate the protocol */
state = endp();
break;
default:
printmsg(0,"process: Unknown state = %c, \
previous system state = %c", state, save_state );
state = XFER_ABORT;
break;
} /* switch */
save_state = old_state; /* Used only if we abort */
} /* while( state != XFER_EXIT ) */
/*--------------------------------------------------------------------*/
/* Update system status */
/*--------------------------------------------------------------------*/
dcstats();
/*--------------------------------------------------------------------*/
/* Protocol is complete, terminate the connection */
/*--------------------------------------------------------------------*/
return CONN_TERMINATE;
} /* process */
/*--------------------------------------------------------------------*/
/* c a n t */
/* */
/* report that we cannot open a critical file */
/*--------------------------------------------------------------------*/
static void cant(char *file)
{
fprintf(stderr, "Can't open: \"%s\"\n", file);
perror( file );
panic();
} /*cant*/